package com.epcs.model.bo;

import java.sql.Date;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import com.epcs.model.dao.EventCategoryDAO;
import com.epcs.model.dao.EventDAO;
import com.epcs.model.dao.FollowingDAO;
import com.epcs.model.dto.Account;
import com.epcs.model.dto.Event;
import com.epcs.model.dto.Eventcategory;
import com.epcs.model.dto.Following;
import com.epcs.model.dto.FullCalendarEvent;
import com.epcs.model.dto.MostFollowingList;
import com.epcs.model.dto.Notification;
import com.epcs.model.dto.android.AndroidEvent;
import com.epcs.model.dto.android.AndroidEventList;
import com.epcs.util.EpcsDateTimeUtil;
import com.epcs.util.MailHandler;

public class EventBO {

	/**
	 * Nó nhận 2 tham số đề thuộc kiểu Event Nếu muốn so sánh bất kỳ event gì thì cũng phải chuyển
	 * về loại system event (Event type)
	 * 
	 * @param firstOne
	 *            event thứ nhất
	 * @param secondOne
	 *            event thứ hai
	 * @return
	 * 
	 *         Event nào lớn thì return event đó. Null khi 2 event giống nhau.
	 * 
	 */
	public static Event getNewestEventBetweenPairOfSystemEvent(Event systemEvent, Event externalEvent) {
		/*
		 * Có thể nó là System event dc parse từ Google hoặc Outlook event. --> không chứa đầy đủ
		 * thông tin --> cần phải lấy thông tin mới updated cho systemEvent --> Và phải kiểm tra !=
		 * 0 của sequence (outlook có sequence khởi tạo = 0)
		 * 
		 * Chú ý: có organizer --> nếu systemEvent mà có cái đó thì mọi thay đổi đều ko dc cập nhật
		 * do organizer là biến cho biết chủ sở hữu event --> null tức là event của mình, != null là
		 * của người khác Mọi event khi tạo ra thì sequence khởi tạo đều = 0.
		 */
		if (systemEvent.getOrganizer() == null) {
			if (externalEvent.getGoogleEventId() != null) {

				// gốc của nó từ Google event hoặc là system --> đều so sequence
				// và updated
				// đối với event loại google và system
				Event googleEvent = externalEvent;
				// so sánh

				// nếu sequence khác nhau
				if (systemEvent.getSequence().intValue() != googleEvent.getSequence().intValue()) {
					// sequence event nào lớn thì return cái đó
					if (systemEvent.getSequence().intValue() > googleEvent.getSequence().intValue()) {
						return systemEvent;

					} else if (systemEvent.getSequence().intValue() < googleEvent.getSequence().intValue()) {
						systemEvent.setDescription(googleEvent.getDescription());
						systemEvent.setIsAllDayEvent(googleEvent.getIsAllDayEvent());
						systemEvent.setIsRecurrent(googleEvent.getIsRecurrent());
						systemEvent.setLocation(googleEvent.getLocation());
						// systemEvent.setRecurrence(googleEvent.getRecurrence());
						systemEvent.setVisibility(googleEvent.getVisibility());
						systemEvent.setUpdated(googleEvent.getUpdated());
						systemEvent.setTitle(googleEvent.getTitle());
						systemEvent.setStatus(googleEvent.getStatus());
						systemEvent.setEndTime(googleEvent.getEndTime());
						systemEvent.setStartTime(googleEvent.getStartTime());
						systemEvent.setSequence(googleEvent.getSequence());

						systemEvent.setReminderTime(googleEvent.getReminderTime());

						return systemEvent;
					}
				} else {
					// nếu sequence bằng nhau
					// kiểm tra updated_time
					Long systemEventUpdatedTime = EpcsDateTimeUtil.getMillisecondsByString(systemEvent.getUpdated());
					Long googleEventUpdatedTime = EpcsDateTimeUtil.getMillisecondsByString(googleEvent.getUpdated());
					// nếu upd của sys lớn hơn
					if (systemEventUpdatedTime.compareTo(googleEventUpdatedTime) > 0) {
						return systemEvent;
					} else if (systemEventUpdatedTime.compareTo(googleEventUpdatedTime) < 0) {
						// nếu upd của sys nhỏ hơn
						systemEvent.setDescription(googleEvent.getDescription());
						systemEvent.setIsAllDayEvent(googleEvent.getIsAllDayEvent());
						systemEvent.setIsRecurrent(googleEvent.getIsRecurrent());
						systemEvent.setLocation(googleEvent.getLocation());
						// systemEvent.setRecurrence(googleEvent.getRecurrence());
						systemEvent.setVisibility(googleEvent.getVisibility());
						systemEvent.setUpdated(googleEvent.getUpdated());
						systemEvent.setTitle(googleEvent.getTitle());
						systemEvent.setStatus(googleEvent.getStatus());
						systemEvent.setEndTime(googleEvent.getEndTime());
						systemEvent.setStartTime(googleEvent.getStartTime());

						systemEvent.setReminderTime(googleEvent.getReminderTime());

						return systemEvent;
					} else {
						// cả upd lẫn seq đều bằng thì
						// đang suy nghĩ có nên check tip ko hay thôi
						// tạm thời return systemEvent; ;
						return systemEvent;
					}
				}
			} else if (externalEvent.getOutlookEventId() != null) {
				// gốc của nó từ Outlook event
				// đối với event loại outlook và system thì ko có sequence
				Event outlookEvent = externalEvent;
				// so sánh
				// kiểm tra updated_time
				Long systemEventUpdatedTime = EpcsDateTimeUtil.getMillisecondsByString(systemEvent.getUpdated());
				Long outlookEventUpdatedTime = EpcsDateTimeUtil.getMillisecondsByString(outlookEvent.getUpdated());
				if (systemEventUpdatedTime.compareTo(outlookEventUpdatedTime) > 0) {
					return systemEvent;
				} else if (systemEventUpdatedTime.compareTo(outlookEventUpdatedTime) < 0) {
					systemEvent.setDescription(outlookEvent.getDescription());
					systemEvent.setIsAllDayEvent(outlookEvent.getIsAllDayEvent());
					systemEvent.setIsRecurrent(outlookEvent.getIsRecurrent());
					systemEvent.setLocation(outlookEvent.getLocation());
					// systemEvent.setRecurrence(googleEvent.getRecurrence());
					systemEvent.setVisibility(outlookEvent.getVisibility());
					systemEvent.setUpdated(outlookEvent.getUpdated());
					systemEvent.setTitle(outlookEvent.getTitle());
					systemEvent.setStatus(outlookEvent.getStatus());
					systemEvent.setEndTime(outlookEvent.getEndTime());
					systemEvent.setStartTime(outlookEvent.getStartTime());

					systemEvent.setReminderTime(outlookEvent.getReminderTime());

					return systemEvent;
				} else {
					// tức là bằng nhau
					// đang suy nghĩ có nên check tip ko hay thôi
					// tạm thời return null;
					return systemEvent;
				}
			}
		} else {
			// nếu nó là event của người khác (follwing theo người khác)
			// ko lấy gì cả, return systemEvent
			// Chú ý: có trường hợp user cố tình update data trên google là sequence bị thay đổi
			// nếu không update sequence lại, có nguy cơ bị crash khi đồng bộ
			// vì vậy phải update sequence cho system Event
			// ??? có mnên cập nhật updated_time ko
			if (externalEvent.getGoogleEventId() != null) {
				// đối với event loại google và system
				Event googleEvent = externalEvent;
				systemEvent.setSequence(googleEvent.getSequence());
			}
			
			return systemEvent;
		}
		return null;
	}

	public List<FullCalendarEvent> getFullCalendarEventList(String start, String end, Account account) {
		List<FullCalendarEvent> list = new ArrayList<FullCalendarEvent>();
		List<Event> eventlist = new ArrayList<Event>();

		EventDAO dao = new EventDAO();
		eventlist = dao.getEventByDatetime(start, end, account);

		if (eventlist != null) {
			for (int i = 0; i < eventlist.size(); i++) {
				Event event = eventlist.get(i);
				FullCalendarEvent fullCalendarEvent = new FullCalendarEvent();

				fullCalendarEvent.setId(event.getEventId());
				fullCalendarEvent.setStart(event.getStartTime());
				fullCalendarEvent.setEnd(event.getEndTime());
				fullCalendarEvent.setTitle(event.getTitle());
				fullCalendarEvent.setAllDay(event.getIsAllDayEvent());
				String status = event.getStatus();
				if (status.equals("confirmed")) {
					list.add(fullCalendarEvent);
				}

				// ---- So sanh thoi gian --> color ---//
				// lay thoi gian cua event
				String startOfEvent = event.getStartTime();
				String endOfEvent = event.getEndTime();
				// lay thoi gian hien tai
				String curent = EpcsDateTimeUtil.getCurrentIsoDateTime();

				/**
				 * Co 3 mau: Xanh, Do, Xanh La. -Do: Khi curent > start va curent < end - Green: Khi
				 * curent > end - blue: Khi curent < start
				 */
				// so sanh thoi gian
				if (curent.compareTo(startOfEvent) > 0 && curent.compareTo(endOfEvent) < 0) {
					fullCalendarEvent.setClassName("eventGreen");
					// } else if (curent.compareTo(startOfEvent) < 0) {
					// fullCalendarEvent.setClassName("eventBlue");
				} else if (curent.compareTo(endOfEvent) > 0) {
					fullCalendarEvent.setClassName("eventRed");
				}
			}
		} else {
			return null;
		}
		return list;
	}

	// Tạo event
	public int createEvent(Event event) {
		EventDAO dao = new EventDAO();
		int result = dao.addEvent(event);

		return result;
	}

	// Update Event
	public boolean updateEvent(Event event) {
		EventDAO dao = new EventDAO();
		boolean result = dao.updateEvent(event);

		return result;
	}

	// cancel Event
	/**
	 * Cancel một event trong hệ thống. Điều kiện event phải có account != null --> event hệ thống.
	 * Vì event khác event hệ thống, hoặc event dc parse từ event khác (android event to system
	 * event) thì không thể có account dc --> không thể cancel dc --- Làm như vậy để dảm bảo an toàn
	 * cho hệ thống. Tránh trường hợp system event ko có, external event có, nhưng lại thực thi bằng
	 * external event --> gây lỗi null pointer, mất vết data...
	 * 
	 * @param event
	 * @return
	 */
	public boolean cancelEvent(Event event) {
		EventDAO eventDAO = new EventDAO();
		FollowingBO followingBO = new FollowingBO();
		boolean result = false;
		Account account = event.getAccount();

		if (account != null) {
			// set cancelled cho event
			event.setStatus("cancelled");
			// set dirty = true
			event.setDirty(true);
			event.setUpdated(EpcsDateTimeUtil.getCurrentIsoDateTime());
			event.setSequence(event.getSequence() + 1);

			// tìm trong following có id của nó ko
			List<Following> followingList = followingBO.getFollowingByEventID(event.getEventId());

			// nếu có đứa follow theo
			if (followingList != null) {
				// thông báo notify tới các user là event đã hủy
				// chú ý ko cần thông báo cho chủ sở hữu
				// -------------Nhân làm-------------//
			
				// Nếu bằng null, nghĩa là đây là event chính--> phải là event chính mới thông báo cho những ng follow
				if(event.getOriginalEvent() ==  null){
					List<Integer> followingIdList = new ArrayList<Integer>();
					 
					for(int i = 0 ; i < followingList.size(); i ++){
						followingIdList.add(followingList.get(i).getFollowingId());
					}
					Account eventCreater = event.getAccount();
					
					//Lấy list follow event cần xóa, nhưng trừ creater ra. Bởi vỉ k cần tạo notification cho chính ng tạo
					List<Following> followingListExceptCreater = followingBO.getFollowingListByFollowingIdList(followingIdList, eventCreater);
					
					//Duyệt list followinng để tạo notification cho những ng đang theo dõi
					if(followingListExceptCreater != null){
						NotificationBO notificationBO = new NotificationBO();
						for(int i = 0 ; i < followingListExceptCreater.size(); i ++){
							
							Notification notificationInfo = new Notification();
							notificationInfo.setFollowing(followingListExceptCreater.get(i));
							notificationInfo.setContent("Có một sự kiện bạn đang quan tâm đã bị hủy.");
							notificationInfo.setStatus(0);
							notificationInfo.setTypeOfNotification("info");
							notificationInfo.setLastUpdated(EpcsDateTimeUtil.getCurrentIsoDateTime());
							notificationBO.insertNotification(notificationInfo);
						}
					}
				}
			
				// ----------------------------------//

				// tìm các event con của nó
				List<Event> subEventList = eventDAO.getSubEventFromDB(event);
				// với mỗi event con--> chuyển status của nó sang cancelled
				for (int i = 0; i < subEventList.size(); i++) {
					Event subEventItem = subEventList.get(i);
					subEventItem.setUpdated(EpcsDateTimeUtil.getCurrentIsoDateTime());
					subEventItem.setStatus("cancelled");
					// set dirty = true
					event.setDirty(true);
					// do mục đích là đảm bảo sync nên cần phải cẩn thận
					/**
					 * Nếu chỉ cancel --> nếu event con sau 2 ngày ko dc sync mà event chính sẽ
					 * cần phải xóa. Vậy sẽ gậy tình trang ko xóa dc event chính. Do khóa chính
					 * khóa phụ
					 * 
					 * Nếu xóa event con đi khi xóa event chính sẽ gây tình trạng bất đồng bộ.
					 * Mất external ID. Khi đó event trên external sẽ quay trở lại.
					 * 
					 * Vì vậy phải set null cho originalID: Vì: khi cancel thì event ko còn thấy
					 * nữa. Ko tương tác nữa. Chỉ chờ sync để xóa. Null original tạo điều kiện
					 * cho main event xóa dc khi dc sync.
					 * 
					 */

					subEventItem.setOriginalEvent(null);

					// update lai sub event
					eventDAO.updateEvent(subEventItem);
				}
			}
			
			
			// về việc unfollow : có 2 trường hợp là
			// 1. của mình tạo -->  khong lam gi ca, chi update thoi
			// 2. của người ta tạo, và mình follow theo --> thì phải
			if (event.getOrganizer() != null){
				// unfollow event chính
				Event mainEvent = event.getOriginalEvent();
				boolean isUnfollowed = followingBO.unfollowingEventOrCategory(mainEvent, account);
				// cuối cùng là update lại event thành cancelled
			}
				
			result = eventDAO.updateEvent(event);
		}

		return result;
	}

	// delete Event
	/**
	 * Hàm này delete event. Trong đó lại xét tới event đang confirmed hay đã cancelled. Nếu là
	 * confirmed thì chuyển nó thành cancelled. Xong xét nó là public hay private. #Nếu là private
	 * thì xóa luôn #Nếu là public thì phải xét: nếu còn đang dc follow thì cho nó 2 ngày tồn tại.
	 * và gởi thông báo cho các user đang follow báo cáo đã hủy. Quá hạn thì gởi mail cho các user
	 * chưa đọc thông báo. Nếu là cancelled thì cũng xét public hay private. Private thì hủy luôn.
	 * Public thì giống với confirmed
	 * 
	 * @param event
	 * @param account
	 * @return
	 */
	public boolean deleteEvent(Event event, Account account) {
		EventDAO eventDAO = new EventDAO();
		FollowingBO followingBO = new FollowingBO();

		try {
			if (event.getStatus().equals("confirmed")) {
				// là event đang hoạt động thì 
				// dù public hay private thì cũng có thể có following
				// xét following có > 1 hay ko (tức là có người khác user follow nó)
				int numberOfFollowing = followingBO.getNumberOfFollowingByEvent(event);
				
				// nếu có người đang follow 
				if (numberOfFollowing > 1) {
					// thực thi cancel mà thôi 
					//(cancel bao gồm cả unfollow event nếu có) --> chi tết: xem hàm
					cancelEvent(event);
					// và báo cho các follower là nó bị hủy
					
				} else {
					// event ko ai theo dõi, thực hiện 2 bước cancel và xóa luôn
					/**
					 * nguyên nhân phải cancel là có liên quan đến nhiều điều kiện
					 * Xem hàm để bit chi tiết
					 */
					cancelEvent(event);
					// chỉ có chủ của nó follow --> unfollow 
					followingBO.unfollowingEventOrCategory(event, account);
					// rồi xóa event
					eventDAO.deleteEvent(event);
				}
			} else {
				// là event bị cancel
				// xét following của nó có lớn hơn 1 ko
				int numberOfFollowing = followingBO.getNumberOfFollowingByEvent(event);

				if (numberOfFollowing > 1) {
					// còn đang dc follow bởi nhiều người
					// chưa thể xóa dc, phải xem có quá hạn ko
					long lastUpdatedTime = EpcsDateTimeUtil.getMillisecondsByString(event.getUpdated());
					long currentTime = EpcsDateTimeUtil.getMillisecondsByString(EpcsDateTimeUtil
							.getCurrentIsoDateTime());

					if (currentTime - lastUpdatedTime > Long.parseLong("172800000")) {
						// Sau 2 ngày bị cancel --> xóa
						// --- các bước để xóa---//
						// tìm tất cả user follow theo event
						List<Account> accountList = followingBO.getAllAccountFollowEvent(event.getEventId());
						/**
						 * gửi mail cho từng user
						 */
						if (accountList != null) {
							for (int i = 0; i < accountList.size(); i++) {
								MailHandler mail = new MailHandler();
								String content = "Thông tin chi tiết: </br>" + "Tên sự kiện: " + event.getTitle()
										+ "</br>" + "Thời gian: Từ " + event.getStartTime() + " đến"
										+ event.getEndTime() + "</br>" + "Địa điểm: " + event.getLocation();
								String title = "Sự kiện bạn đang theo dõi vừa bị xóa";
								mail.sendEMail(accountList.get(i).getUsername(), content, title);
								Thread thread = new Thread(mail);
								thread.start();
								System.out.println("Verified Mail has been sent!");
							}
						}

						// hủy follow đi
						for (int i = 0; i < accountList.size(); i++) {
							// xóa following nếu có
							followingBO.unfollowingEventOrCategory(event, accountList.get(i));
						}

						// xóa event chính
						eventDAO.deleteEvent(event);
					}
					// ko quá hạn thì ko làm gì hết, ko add cung ko xoa

				} else {
					// chỉ có chủ của nó follow --> xóa
					followingBO.unfollowingEventOrCategory(event, account);
					// xóa event
					eventDAO.deleteEvent(event);
				}
			}
		} catch (Exception ex) {
			ex.printStackTrace();
			return false;
		}

		return true;
	}

	// Get tat ca Event thuoc account login
	public List<Event> getAllEvent(Account account) {

		List<Event> allEvent = new ArrayList<Event>();
		EventDAO dao = new EventDAO();
		allEvent = dao.getEventListFromDB(account);

		for (int i = 0; i < allEvent.size(); i++) {
			Event event = allEvent.get(i);
			event.setStartTime(EpcsDateTimeUtil.convertToJSPDatetime(event.getStartTime()));
			event.setEndTime(EpcsDateTimeUtil.convertToJSPDatetime(event.getEndTime()));
		}

		return allEvent;
	}
	// Get tat ca Event thuoc account login dùng cho sync
	public List<Event> getAllEventForSync(Account account) {
		
		List<Event> allEvent = new ArrayList<Event>();
		EventDAO dao = new EventDAO();
		allEvent = dao.getEventListFromDBForSync(account);
				
		return allEvent;
	}

	// Get tat ca Event thuoc co cung OrginalEventID
	public List<Event> getAllOrginalEvent(String eventId) {

		List<Event> allEvent = new ArrayList<Event>();
		EventDAO dao = new EventDAO();
		Event event = new Event();
		try{
			Integer Id = Integer.valueOf(eventId);
			event = dao.getEventFromDB(Id);
			allEvent = dao.getEventListByOrinalId(event);
		} catch(NumberFormatException ex){
			return null;
		}
		return allEvent;
	}

	// Get tat ca Public Event
	public List<Event> getNewEvents(int pageNumber, int maxRecord, Account account) {
		FollowingDAO followDAO = new FollowingDAO();
		EventDAO eventDAO = new EventDAO();
		EventCategoryDAO eventCategoryDAO = new EventCategoryDAO();

		// Lấy list categoryId mà user quan tâm
		List<Integer> listCategoryId = followDAO.getCategoryIdListByAccount(account);
		if (listCategoryId != null) {
			// Lấy list category mà user quan tâm
			List<Eventcategory> userCategoryList = eventCategoryDAO
					.getEventCategoryListByCategoryIdList(listCategoryId);
			// Lấy event list event dựa trên userCategoryList
			List<Integer> eventIdList = eventDAO.getEventIdListByUserCategory(userCategoryList, "startTime", account);
			// filter theo giá trị list vừa nhận được
			List<Event> eventList = eventDAO.getEventListAfterFilter((pageNumber - 1) * maxRecord, maxRecord,
					eventIdList);
			if (eventList != null) {
				for (int i = 0; i < eventList.size(); i++) {
					Event event = eventList.get(i);
					if(event.getDescription().length() > 200 ){
					event.setDescription(event.getDescription().substring(0, 200)+"...");
					}
					event.setStartTime(EpcsDateTimeUtil.convertToJSPDatetime(event.getStartTime()));
					event.setEndTime(EpcsDateTimeUtil.convertToJSPDatetime(event.getEndTime()));
				}
			}
			return eventList;
		}
		return null;
	}

	// Get 1 Event dua vao id cua event do
	public Event getEvent(String eventId) {

		Event eventDetail = new Event();
		EventDAO dao = new EventDAO();
		try{
			Integer Id = Integer.valueOf(eventId);
			eventDetail = dao.getEventFromDB(Id);
			if(eventDetail!= null){
				eventDetail.setStartTime(EpcsDateTimeUtil.convertToJSPDatetime(eventDetail.getStartTime()));
				eventDetail.setEndTime(EpcsDateTimeUtil.convertToJSPDatetime(eventDetail.getEndTime()));
				if(eventDetail.getIsAllDayEvent()==true){
					long endTime = EpcsDateTimeUtil.getMillisecondsByString(eventDetail.getEndTime());
					endTime = endTime - 86400000;
					Date date = new Date(endTime);
					SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
					String newEndTime = format.format(date);
					eventDetail.setEndTime(newEndTime);
				}
			}
		}
		catch(NumberFormatException ex){
			return null;
		}
		
		return eventDetail;
	}

	// Get all event theo category
	public List<Event> getAllPublicEventByCategory(int pageNumber, int maxRecord, Account account,
			Eventcategory categoryItem) {
		EventDAO eventDAO = new EventDAO();
		List<Eventcategory> listEventCategory = new ArrayList<Eventcategory>();
		listEventCategory.add(categoryItem);
		List<Integer> eventIdList = eventDAO.getEventIdListByUserCategory(listEventCategory, "endTime", account);
		if (eventIdList.size() > 0) {
			List<Event> eventList = eventDAO.getEventListAfterFilter((pageNumber - 1) * maxRecord, maxRecord,
					eventIdList);
			for (int i = 0; i < eventList.size(); i++) {
				Event event = eventList.get(i);
				event.setStartTime(EpcsDateTimeUtil.convertToJSPDatetime(event.getStartTime()));
				event.setEndTime(EpcsDateTimeUtil.convertToJSPDatetime(event.getEndTime()));
			}
			return eventList;
		}
		return null;
	}

	// Tao follow event
	public int createFollow(Following follow) {
		EventDAO dao = new EventDAO();
		int result = dao.addFollow(follow);

		return result;
	}

	public AndroidEventList getAllEventForAndroid(Account account) {
		AndroidEventList list = new AndroidEventList();
		List<Event> systemEventList = new EventBO().getAllEventForSync(account);

		for (int i = 0; i < systemEventList.size(); i++) {
			Event systemEvent = systemEventList.get(i);
			AndroidEvent androidEvent = convertSystemEventToAndroiEvent(systemEvent);

			list.add(androidEvent);
		}

		return list;
	}

	public AndroidEventList convertSystemListToAndroidEventList(List<Event> systemEventList) {
		AndroidEventList list = new AndroidEventList();

		for (int i = 0; i < systemEventList.size(); i++) {
			Event systemEvent = systemEventList.get(i);
			AndroidEvent androidEvent = convertSystemEventToAndroiEvent(systemEvent);

			list.add(androidEvent);
		}

		return list;
	}

	public AndroidEvent convertSystemEventToAndroiEvent(Event systemEvent) {
		AndroidEvent androidEvent = new AndroidEvent();

		androidEvent.set_SYNC_ID(String.valueOf(systemEvent.getEventId()));

		Long start = EpcsDateTimeUtil.getMillisecondsByString(systemEvent.getStartTime());
		androidEvent.setDTSTART(start);

		Long stop = EpcsDateTimeUtil.getMillisecondsByString(systemEvent.getEndTime());
		androidEvent.setDTEND(stop);
		
		androidEvent.setTITLE(systemEvent.getTitle());
		
		if (systemEvent.getDescription() == null || systemEvent.getDescription().trim().equals("")){
			androidEvent.setDESCRIPTION("Không có mô tả!");
		} else {
			androidEvent.setDESCRIPTION(systemEvent.getDescription());
		}
		
		androidEvent.setEVENT_LOCATION(systemEvent.getLocation());

		if (systemEvent.getStatus().equals("confirmed")) {
			androidEvent.setSTATUS(AndroidEvent.CONFIRMED);
			androidEvent.setDELETED(Long.valueOf(0));
		} else {
			androidEvent.setSTATUS(AndroidEvent.CANCELED);
			androidEvent.setDELETED(Long.valueOf(1));
		}

		if (systemEvent.getIsAllDayEvent()) {
			androidEvent.setALL_DAY(AndroidEvent.TRUE);
			// androidEvent.setEVENT_TIMEZONE("Asia/Ho_Chi_Minh");
			androidEvent.setEVENT_TIMEZONE("UTC");
		} else {
			androidEvent.setALL_DAY(AndroidEvent.FALSE);
			// androidEvent.setEVENT_TIMEZONE("Asia/Ho_Chi_Minh");
			androidEvent.setEVENT_TIMEZONE("Asia/Saigon");
		}

		if (systemEvent.getDirty()) {
			androidEvent.setDIRTY(AndroidEvent.TRUE);
		} else {
			androidEvent.setDIRTY(AndroidEvent.FALSE);
		}

		if (systemEvent.getVisibility() != null) {
			if (systemEvent.getVisibility().toLowerCase().equals("private")) {
				androidEvent.setACCESS_LEVEL(AndroidEvent.PRIVATE);
			} else {
				androidEvent.setACCESS_LEVEL(AndroidEvent.PUBLIC);
			}
		} else {
			androidEvent.setACCESS_LEVEL(AndroidEvent.PUBLIC);
		}

		androidEvent.setORGANIZER(systemEvent.getOrganizer());
		androidEvent.setSELF_ATTENDEE_STATUS(AndroidEvent.TRUE);
		androidEvent.setREMINDER_MINUTES(Long.valueOf(systemEvent.getReminderTime()));

		return androidEvent;
	}

	public Event convertAndroiEventToSystemEvent(AndroidEvent androidEvent) {
		Event systemEvent = new Event();
		try {
			systemEvent.setEventId(Integer.valueOf(androidEvent.get_SYNC_ID()));
		} catch (java.lang.NumberFormatException ex) {
			systemEvent.setEventId(null);
		}

		String start = EpcsDateTimeUtil.getIsoDateTime(androidEvent.getDTSTART());
		systemEvent.setStartTime(start);

		String stop = EpcsDateTimeUtil.getIsoDateTime(androidEvent.getDTEND());
		systemEvent.setEndTime(stop);

		systemEvent.setLocation(androidEvent.getEVENT_LOCATION());
		systemEvent.setTitle(androidEvent.getTITLE());
		
		if (androidEvent.getDESCRIPTION() == null || androidEvent.getDESCRIPTION().trim().equals("")){
			systemEvent.setDescription("Không có mô tả!");
		} else {
			systemEvent.setDescription(androidEvent.getDESCRIPTION());
		}

		if (androidEvent.getSTATUS().compareTo(AndroidEvent.CONFIRMED) == 0) {
			systemEvent.setStatus("confirmed");
		} else {
			systemEvent.setStatus("cancelled");
		}

		if (androidEvent.getALL_DAY().compareTo(AndroidEvent.TRUE) == 0) {
			systemEvent.setIsAllDayEvent(true);
		} else {
			systemEvent.setIsAllDayEvent(false);
		}

		if (androidEvent.getACCESS_LEVEL().compareTo(AndroidEvent.PRIVATE) == 0) {
			systemEvent.setVisibility("private");
		} else {
			systemEvent.setVisibility("public");
		}

		if (androidEvent.getDIRTY().compareTo(AndroidEvent.TRUE) == 0) {
			systemEvent.setDirty(true);

		} else {
			systemEvent.setDirty(false);
		}
		systemEvent.setIsNotified(false);
		// systemEvent.setOrganizer(androidEvent.getORGANIZER());

		systemEvent.setReminderTime(Integer.parseInt(String.valueOf(androidEvent.getREMINDER_MINUTES())));

		return systemEvent;
	}

	public static Event getNewestEventBetweenPairOfSystemEventForAndroid(Event systemEvent, Event androidEvent) {
		// bắt đầu xét dirty = 1 --> loại update hoặc delet
		if (androidEvent.getDirty()) {
			// nếu sysEvent cũng dirty = 1 (update)--> ưu tiên cho system
			if (systemEvent.getDirty()) {

				// trả lại trạng thái đã cập nhật
				systemEvent.setDirty(Boolean.valueOf(false));
				// set lai sequence
				int sequence = systemEvent.getSequence() + 1;
				systemEvent.setSequence(Integer.valueOf(sequence));

			} else {
				// nhét thông tin mới vào system event
				systemEvent.setDescription(androidEvent.getDescription());
				systemEvent.setIsAllDayEvent(androidEvent.getIsAllDayEvent());
				// systemEvent.setIsRecurrent(androidEvent.getIsRecurrent());
				systemEvent.setLocation(androidEvent.getLocation());
				// systemEvent.setRecurrence(googleEvent.getRecurrence());
				systemEvent.setVisibility(androidEvent.getVisibility());
				systemEvent.setUpdated(EpcsDateTimeUtil.getCurrentIsoDateTime());
				systemEvent.setTitle(androidEvent.getTitle());
				systemEvent.setStatus(androidEvent.getStatus());
				systemEvent.setEndTime(androidEvent.getEndTime());
				systemEvent.setStartTime(androidEvent.getStartTime());
				int sequence = systemEvent.getSequence() + 1;
				systemEvent.setSequence(Integer.valueOf(sequence));
				systemEvent.setReminderTime(androidEvent.getReminderTime());
			}
		} else {
			// khi android thuộc dạng nochange
			// nếu sysEvent dirty = 1 (update)--> ưu tiên cho system
			if (systemEvent.getDirty()) {

				// trả lại trạng thái đã cập nhật
				systemEvent.setDirty(Boolean.valueOf(false));
				// set lai sequence
				int sequence = systemEvent.getSequence() + 1;
				systemEvent.setSequence(Integer.valueOf(sequence));

			} else {
				// system event dirty = 0 --> nochange
				return null;

			}
		}

		return systemEvent;
	}

	public List<Event> getCommingEvent(List<Integer> listEventId, int firstPosition, int maxRecord) {
		EventDAO eventDAO = new EventDAO();
		return eventDAO.getCommingEvent(listEventId, firstPosition, maxRecord);
	}

	public List<Event> getCloneEvent(Account account, Event originalEvent) {
		EventDAO eventDAO = new EventDAO();
		return eventDAO.getCloneEvent(account, originalEvent);
	}
public List<Object> getTopFollowedEventByUser(int firstRecord, int maxRecord, Account account){
	EventDAO eventDAO = new EventDAO();
	FollowingDAO followingDAO = new FollowingDAO();
	List<Object> objectList = new ArrayList<Object>();
	// lấy list các event
	List<Event> eventList = eventDAO.getEventListByAccount(account);
	List<Integer> eventIdList = new ArrayList<Integer>();
	// Nếu list khác nên thì lấy ra các eventId khi mà event là cùa chính nó
	if(eventList != null){
		for(int i = 0 ;i <eventList.size();i++){
			if(eventList.get(i).getOrganizer() == null){
				eventIdList.add(eventList.get(i).getEventId());
			}
		}
		List<MostFollowingList> mostFollowingList = followingDAO.getMostFollowingList(firstRecord, maxRecord, eventIdList);
		if(mostFollowingList != null){
			//nhét objectList
			objectList.add(mostFollowingList);
			//duyệt list eventId
				List<Event> listEvent = new ArrayList<Event>();

				for (int i = 0; i < mostFollowingList.size(); i++) {
					// lấy 1 trong những event được follow nhìu nhất
					Event event = eventDAO.getEventByEventId(mostFollowingList.get(
							i).getIdOfFollow());
					if (event.getDescription().length() > 100) {
						String desc = event.getDescription().substring(0, 100);
						event.setDescription(desc + "...");
					}
					event.setStartTime(EpcsDateTimeUtil.convertToJSPDatetime(event
							.getStartTime()));
					event.setEndTime(EpcsDateTimeUtil.convertToJSPDatetime(event
							.getEndTime()));
					// add event vào list
					listEvent.add(event);
				}
				//nhét objectList
				objectList.add(listEvent);
			}
		}
	return objectList;
}
}
